www.gusucode.com > VC++ 解析emf文件结构并显示-源码程序 > VC++ 解析emf文件结构并显示-源码程序/code/EmfReader/EmfReaderDlg.cpp

    //Download by http://www.NewXing.com
// EmfReaderDlg.cpp : 实现文件
//

#include "stdafx.h"
#include "EmfReader.h"
#include "EmfReaderDlg.h"
#include "Wingdi.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// 对话框数据
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 实现
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CEmfReaderDlg 对话框




CEmfReaderDlg::CEmfReaderDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CEmfReaderDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CEmfReaderDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CEmfReaderDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_BN_CLICKED(IDOK, &CEmfReaderDlg::OnBnClickedOk)
	ON_BN_CLICKED(IDC_BUTTON_NEXT, &CEmfReaderDlg::OnBnClickedButtonNext)
	ON_BN_CLICKED(IDCANCEL, &CEmfReaderDlg::OnBnClickedCancel)
END_MESSAGE_MAP()


// CEmfReaderDlg 消息处理程序

BOOL CEmfReaderDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// 将“关于...”菜单项添加到系统菜单中。

	// IDM_ABOUTBOX 必须在系统命令范围内。
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
	//  执行此操作
	SetIcon(m_hIcon, TRUE);			// 设置大图标
	SetIcon(m_hIcon, FALSE);		// 设置小图标

	// TODO: 在此添加额外的初始化代码
	Initialize( ) ;

	return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

void CEmfReaderDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// 如果向对话框添加最小化按钮,则需要下面的代码
//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,
//  这将由框架自动完成。

void CEmfReaderDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 用于绘制的设备上下文

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// 使图标在工作矩形中居中
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// 绘制图标
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		if( m_hDCMem && m_EnhMetaHeader.szlDevice.cx > 0 )
		{
			HDC hDC = ::GetWindowDC(m_hWnd) ;
			// Capture screen into bitmap
			//RT_INFO_TRACE_THIS("CMirrorDriverManager::CaptureScreen.BEGIN rect:" <<rect.tl.x << ","<<rect.tl.y << "," <<rect.br.x << "," <<rect.br.y ) ;
			RECT rect ;
			GetClientRect( & rect ) ;
			int nOldMode = SetStretchBltMode( m_hDCMem, STRETCH_HALFTONE); 
			//BOOL bRet = BitBlt( hDC, rect.left + 5, rect.top + 30 ,
			//		(rect.right-rect.left) - 5 ,
			//		(rect.bottom-rect.top)-100,
			//		m_hDCMem , 800 , 800 ,   SRCCOPY ) ;
			BOOL blitok = StretchBlt(hDC, rect.left + 5, rect.top + 30 ,
				(rect.right-rect.left) - 5 ,
				(rect.bottom-rect.top)-100,
				m_hDCMem , 0 , 0 , m_EnhMetaHeader.szlDevice.cx   , m_EnhMetaHeader.szlDevice.cy  ,   SRCCOPY  ) ;
			//RT_INFO_TRACE_THIS("CMirrorDriverManager::CaptureScreen.END") ;
			SetStretchBltMode( m_hDCMem, nOldMode); 

			// Select the old bitmap back into the memory DC
			::ReleaseDC( m_hWnd , hDC ) ;
		}
		CDialog::OnPaint();
	}
}

//当用户拖动最小化窗口时系统调用此函数取得光标显示。
//
HCURSOR CEmfReaderDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}


void CEmfReaderDlg::OnBnClickedOk()
{
	CString szFilter( L"Emf Files (*.emf)|*.emf||" ) ;

	CFileDialog FileDlg(TRUE,CString( L"EMF") ,NULL,
		OFN_FILEMUSTEXIST|OFN_NONETWORKBUTTON|
		OFN_PATHMUSTEXIST,szFilter);
	FileDlg.DoModal();

	// To get the selected file's path and name
	CString strFileName;
	strFileName = FileDlg.GetPathName();

	if(strFileName.IsEmpty())
		return ;
	TRACE(L"FileName:%s\n",strFileName) ;
	memset( &m_EnhMetaHeader , 0 , sizeof( ENHMETAHEADER ) ) ;
	m_strEmfFile = strFileName ;

	if( m_File.GetFileName().GetLength() > 0 )
		m_File.Close() ; 
	if (!m_File.Open(strFileName ,CFile::modeRead , &m_FileException))
	{
		TCHAR szError[1024];
		m_FileException.GetErrorMessage(szError, 1024);
		TRACE(L"Couldn't open source file::%s,errormsg:s\n",strFileName,szError) ;
		return ;
	}
	DWORD dwReaded ;
	dwReaded = m_File.Read( &m_EnhMetaHeader , sizeof( ENHMETAHEADER ) ) ;
	if( dwReaded < sizeof( ENHMETAHEADER ) )
	{
		TRACE("Read meta header error!\n") ;
		m_File.Close() ;
		return ;
	}
	if( m_EnhMetaHeader.dSignature!=0x464d4520)
	{
		TRACE("This file is not emf file.\n");
		m_File.Close() ;
		return; 
	}
	if ( m_EnhMetaHeader.nDescription > 0 )
	{
		//file.Seek(eh.offDescription,CFile::begin);
		TCHAR *szDesciption ;
		szDesciption = new TCHAR[m_EnhMetaHeader.nDescription+1] ;
		memset( szDesciption , 0 , sizeof( TCHAR) * (m_EnhMetaHeader.nDescription+1));
		dwReaded = m_File.Read(szDesciption , m_EnhMetaHeader.nDescription * sizeof( TCHAR) ) ;
		if( dwReaded == m_EnhMetaHeader.nDescription * sizeof( TCHAR) )
		{
			TRACE(L"description:%s\n",szDesciption);
		}
		//file.Seek( sizeof( ENHMETAHEADER ) , CFile::begin) ;
		delete szDesciption ;
	}
	CreateMemDCandBitmap() ;
	m_dwEmfRecord = 0 ;
}
void CEmfReaderDlg::DoRecord( DWORD iType , DWORD nSize , LPBYTE lpData ) 
{
	switch( iType )
	{
	case EMR_SETPIXELV:
	case EMR_SETMAPPERFLAGS:
	case EMR_SETCOLORADJUSTMENT:
	case EMR_OFFSETCLIPRGN:
	case EMR_SCALEVIEWPORTEXTEX:
	case EMR_SCALEWINDOWEXTEX:
	case EMR_SETWORLDTRANSFORM:
	case EMR_SELECTPALETTE:
	case EMR_CREATEPALETTE:
	case EMR_SETPALETTEENTRIES:
	case EMR_RESIZEPALETTE:
	case EMR_EXTFLOODFILL:
	case EMR_POLYDRAW:
	case EMR_SETARCDIRECTION:
	case EMR_SETMITERLIMIT:
	case EMR_GDICOMMENT:
	case EMR_FRAMERGN:
	case EMR_INVERTRGN:
	case EMR_PAINTRGN:
	case EMR_STRETCHBLT:
	case EMR_MASKBLT:
	case EMR_PLGBLT:
	case EMR_SETDIBITSTODEVICE:
	case EMR_POLYDRAW16:
	case EMR_CREATEMONOBRUSH:
	case EMR_CREATEDIBPATTERNBRUSHPT:
	case EMR_POLYTEXTOUTA:
	case EMR_POLYTEXTOUTW:
	case EMR_CREATECOLORSPACE:
	case EMR_GLSRECORD:
	case EMR_GLSBOUNDEDRECORD:
	case EMR_PIXELFORMAT:
	case EMR_RESERVED_105:
	case EMR_RESERVED_106:
	case EMR_RESERVED_107:
	case EMR_RESERVED_108:
	case EMR_RESERVED_109:
	case EMR_RESERVED_110:
	case EMR_COLORCORRECTPALETTE:
	case EMR_SETICMPROFILEA:
	case EMR_SETICMPROFILEW:
	case EMR_ALPHABLEND:
	case EMR_TRANSPARENTBLT:
	case EMR_RESERVED_117:
	case EMR_GRADIENTFILL:
	case EMR_RESERVED_119:
	case EMR_RESERVED_120:
	case EMR_COLORMATCHTOTARGETW:
	case EMR_CREATECOLORSPACEW:
		TRACE("RECORDTYPE:%ld,size:%ld\n",iType , nSize) ;
		break ;
	case EMR_EOF:
	case EMR_HEADER:
		break ;
	case EMR_POLYLINE:
	case EMR_POLYBEZIER :
	case EMR_POLYGON:
	case EMR_POLYBEZIERTO:
	case EMR_POLYLINETO:
		EmrPolyX(  lpData ) ;
		break ;
	case EMR_POLYLINE16:
	case EMR_POLYBEZIER16 :
	case EMR_POLYGON16:
	case EMR_POLYBEZIERTO16:
	case EMR_POLYLINETO16:
		EmrPoly16X(  lpData ) ;
		break ;
	case EMR_BITBLT:
		EmrBitBlt(  lpData ) ;
		break ;
	case EMR_EXTTEXTOUTA:
	case EMR_EXTTEXTOUTW:
		EmrExtTextOutW(  lpData ) ;
		break ;
	case EMR_STRETCHDIBITS:
		EmrStretchDibits( lpData ) ;
		break ;
	case EMR_SELECTOBJECT:
		EmrSelectObject( lpData , FALSE ) ;
		break ;
	case EMR_DELETEOBJECT:
		EmrSelectObject( lpData , TRUE ) ;
		break ;
	case EMR_ABORTPATH:
	case EMR_BEGINPATH:
	case EMR_ENDPATH:
	case EMR_CLOSEFIGURE:
	case EMR_FLATTENPATH:
	case EMR_WIDENPATH:
	case EMR_SETMETARGN:
	case EMR_SAVEDC:
	case EMR_REALIZEPALETTE:
		EmrDC( lpData ) ;
		break ;
	case EMR_RESTOREDC:
		EmrRestoreDC( lpData ) ;
		break ;
	case EMR_MOVETOEX:
	case EMR_LINETO:
		EmrMoveX( lpData ) ;
		break ;
	case EMR_SETTEXTCOLOR:
	case EMR_SETBKCOLOR:
		EmrSetBkOrTextColor( lpData ) ;
		break ;
	case EMR_SELECTCLIPPATH:
	case EMR_SETBKMODE:
	case EMR_SETMAPMODE:
	case EMR_SETPOLYFILLMODE:
	case EMR_SETROP2:
	case EMR_SETSTRETCHBLTMODE:
	case EMR_SETTEXTALIGN:
	case EMR_SETICMMODE:
	case EMR_SETLAYOUT:
		EmrSetBkOrOtherMode(lpData) ;
		break ;
	case EMR_SETWINDOWEXTEX:
	case EMR_SETVIEWPORTEXTEX:
		EmrSetWindowOrViewPortExtEX(lpData) ;
		break ;		
	case EMR_SETWINDOWORGEX:
	case EMR_SETVIEWPORTORGEX:
	case EMR_SETBRUSHORGEX:
		EmrSetWindowOrViewPortEX(lpData) ;
		break ;		
	case EMR_EXTCREATEFONTINDIRECTW:
		EmrExtCreateFontIndirectW( lpData ) ;
		break ;
	case EMR_SETCOLORSPACE:
	case EMR_DELETECOLORSPACE:
		EmrSetColorSpace( lpData ) ;
		break ;
	case EMR_CREATEBRUSHINDIRECT:
		EmrCreateBrushIndirect( lpData ) ;
		break ;
	case EMR_EXTCREATEPEN:
		EmrExtCreatePen( lpData ) ;
		break ; 
	case EMR_MODIFYWORLDTRANSFORM:
		EmrModifyWorldTransForm( lpData ) ;
		break ; 
	case EMR_EXTSELECTCLIPRGN:
		EmrExtSelectClipRgn( lpData ) ;
		break ; 
	case EMR_INTERSECTCLIPRECT:
	case EMR_EXCLUDECLIPRECT:
		EmrInterSelectClipRect( lpData ) ;
		break ;
	case EMR_FILLPATH:
	case EMR_STROKEANDFILLPATH:
	case EMR_STROKEPATH:
		EmrStrokePath( lpData ) ;
		break ;
	case EMR_POLYPOLYLINE16:
	case EMR_POLYPOLYGON16:
		EmrPolyPolyLine16( lpData ) ;
		break ;
	case EMR_POLYPOLYLINE:
	case EMR_POLYPOLYGON:
		EmrPolyPolyLine( lpData ) ;
		break ;
	case EMR_CREATEPEN:
		EmrCreatePen( lpData ) ;
		break ; 
	case EMR_ANGLEARC:
		EmrAngleArc( lpData ) ;
		break ; 
	case EMR_ELLIPSE:
	case EMR_RECTANGLE:
		EmrRectangle( lpData ) ;
		break ;
	case EMR_ROUNDRECT:
		EmrRoundRect( lpData ) ;
		break ; 
	case EMR_ARC:
	case EMR_CHORD:
	case EMR_ARCTO:
	case EMR_PIE:
		EmrArc( lpData ) ;
		break ; 
	case EMR_FILLRGN:
		EmrFillRgn( lpData ) ;
		break ; 
	}
}

void CEmfReaderDlg::OnBnClickedButtonNext()
{
	DWORD iType ;
	DWORD nSize ;
	LPBYTE lpParam ;
	while( TRUE )
	{
		if( m_File.GetFileName().GetLength() == 0 )
			return ;
		DWORD dwReaded = m_File.Read( &iType , 4 ) ;
		if( dwReaded < 4 )
			return ;
		dwReaded = m_File.Read( &nSize , 4 ) ;
		if( dwReaded < 4 )
			return ;
		lpParam = new BYTE[nSize ];
		memset( lpParam , 0 , nSize ) ;
		memcpy( lpParam , &iType , 4 ) ; 
		memcpy( lpParam + 4 , &nSize , 4 ) ; 
		if( lpParam == NULL )
			return ;
		if( nSize > 8 )
		{
			dwReaded = m_File.Read(lpParam + 8, nSize - 8 ) ;
			if( dwReaded < nSize - 8  )
				return ;
		}
		m_dwEmfRecord ++ ;
		TRACE("recorder:%ld:",m_dwEmfRecord ) ;
		DoRecord( iType , nSize  , lpParam ) ;
		delete lpParam ;
		if( iType == EMR_EOF || m_dwEmfRecord % 20 == 0 )
		{
			OnPaint();
			if( iType == EMR_EOF )
			{
				m_File.Close() ;
				return ;

			}
		}
	}

}

void CEmfReaderDlg::OnBnClickedCancel()
{
	UnInitialize() ;
	OnCancel();
}
void CEmfReaderDlg::Initialize( ) 
{
	m_dwEmfRecord = 0 ;
	m_hDCMem = NULL ;               // Handle to the memory device context
	m_hBitmap = NULL ;          // Handle to the new bitmap
}
void CEmfReaderDlg::ReleaseAllObjs() 
{
	if( m_hBitmap )
	{
		DeleteObject( m_hBitmap ) ;
		m_hBitmap = NULL ;
	}
	if( m_hDCMem )
	{
		DeleteDC( m_hDCMem ) ;
		m_hDCMem = NULL ;
	}
	list<HGDIOBJECT_NODE>::iterator it , it1 ;

	it = m_listGdiObj.begin() ;
	while( it != m_listGdiObj.end( ) )
	{
		it1 = it ;
		it++ ;
		HGDIOBJECT_NODE node = (HGDIOBJECT_NODE)(*it1) ;
		DeleteObject( node.hGidObj ) ;
		m_listGdiObj.erase( it1 ) ;
	}
}

void CEmfReaderDlg::UnInitialize() 
{
	if( m_File.GetFileName().GetLength() > 0 )
		m_File.Close() ;
	ReleaseAllObjs( ) ;
}
BOOL CEmfReaderDlg::CreateMemDCandBitmap() 
{
	ReleaseAllObjs( ) ;

	// Retrieve the width and height of window display elements.
	long iWidth = m_EnhMetaHeader.szlDevice.cx ;
	long iHeight = m_EnhMetaHeader.szlDevice.cy ;
	if( iWidth == 0 || iHeight == 0 )
		return FALSE ;


	HDC hDC = ::GetWindowDC(m_hWnd) ;
	if( hDC == NULL )
		return FALSE ;
	m_hDCMem = CreateCompatibleDC (hDC);
	if( m_hDCMem == NULL )
	{
		::ReleaseDC( m_hWnd ,  hDC ) ;
		return FALSE ;
	}

	// Create a bitmap compatible with the device associated with the 
	// device context.
	m_hBitmap = CreateCompatibleBitmap (hDC, iWidth, iHeight);
	if( m_hBitmap == NULL )
	{
		if( m_hDCMem )
		{
			DeleteDC( m_hDCMem ) ;
			m_hDCMem = NULL ;
		}
		::ReleaseDC( m_hWnd ,  hDC ) ;
		return FALSE ;

	}
	HBITMAP oldbitmap;
	oldbitmap = (HBITMAP) SelectObject( m_hDCMem, m_hBitmap );
	RECT rc ;
	rc.left = 0 ;
	rc.top = 0 ;
	rc.right = iWidth ; 
	rc.bottom = iHeight ; 
	FillRect(m_hDCMem, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH)) ;

	::ReleaseDC( m_hWnd ,  hDC ) ;
	return TRUE ;
}